package com.suray.wcs.res.msgparse;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.utils.Action;
import com.suray.wcs.res.enums.Order;

import java.util.List;


/**
 * @author Doofy&xuhang
 */
public class MsgTransferUtil {
    public static void main(String[] args) {
        byte[] bs = new byte[]{0, 0, 0};
        int index_bits = 3;
        int len = 8;
        int value = 128;
        setValues(bs, index_bits, len, value);
        int values = getValues(bs, index_bits, len);
        System.out.println(values);
        for (byte b : bs) {
            System.out.println(b);
        }
    }

    /**
     * 给报文赋值
     *
     * @param bs         byte数组，报文
     * @param index_bits 值在报文里的起始下标
     * @param len        值的长度
     * @param value      值
     */
    public static void setValues(byte[] bs, int index_bits, int len, int value) {
        // 数据检验
        if (len < 1 || len > 32 || value < 0 || null == bs || bs.length < 1 || index_bits < 0
                || index_bits > (bs.length) * 8 || len < Integer.toBinaryString(value).length()) {
            throw new RuntimeException("参数数据超出范围");
        }
        int startIndex = index_bits;// 值在报文里的起始下标
        int firstArrayIndex = startIndex >>> 3;// 值在报文中的第一个数组的下标
        int firstBit = startIndex & 7;// 值在报文中第一个数组的起始位（1-7针对于一个字节）
        int endIndex = index_bits + len - 1;// 值在报文中的最后一个下标
        int lastArrayIndex = endIndex >>> 3;// 值在报文中的最后一个数组的下标
        int lastBit = endIndex & 7;// 值在报文中最后一个数组的末尾位
        // 新修改
        if (firstArrayIndex == lastArrayIndex) {
            // 做初始化
            int temp = ~(((((0xff << firstBit) & 0xff) >>> (8 - len)) << (7 - lastBit)) & 0xff);
            bs[firstArrayIndex] &= temp;
            value = ((value << (8 - len)) & 0xff) >>> firstBit;
            bs[firstArrayIndex] = (byte) (bs[firstArrayIndex] | value);
        } else {
            int length = lastArrayIndex - firstArrayIndex + 1;// 值所占用byte数组的长度（几个byte数组需要修改）

            // 第一个数据初始化并赋值
            int firstTemp = ~((((0xff << firstBit) & 0xff) >>> (firstBit)) & 0xff);
            bs[firstArrayIndex] &= firstTemp;

            bs[firstArrayIndex] |= ((value >>> ((length - 2) * 8 + 1 + lastBit)));
            value = (value << (7 - lastBit));// 先进行补位,value补位考虑32位int超出范围,超出部分已经预先填入
            // 最后一个数据初始化
            int lastTemp = (0xff >>> (lastBit + 1));
            bs[lastArrayIndex] &= lastTemp;
            int index = 0;
            for (int i = 0; i < length - 1; i++) {
                index = lastArrayIndex - i;
                // 中间数据初始化
                if (i > 0) {
                    index = lastArrayIndex - i;
                    bs[index] &= 0;
                }
                bs[index] |= ((value >>> 8 * i) & 0xff);// 为除第一个byte数组赋值
            }
        }
    }

    public static int getValues(byte[] bs, int index_bits, int len) {
        // 获取数据检验
        if (len < 1 || len > 32 || null == bs || bs.length < 1 || index_bits < 0 || index_bits > (bs.length) * 8) {
            throw new RuntimeException("参数数据超出范围");
        }
        int result = 0;
        int startIndex = index_bits;
        int firstArrayIndex = startIndex >>> 3;
        int firstBit = startIndex & 7;
        int endIndex = index_bits + len - 1;
        int lastArrayIndex = endIndex >>> 3;
        int lastBit = endIndex & 7;
        if (firstArrayIndex == lastArrayIndex) {
            // 在同一个字节里
            int temp = (((bs[firstArrayIndex] << firstBit) & 0xff) >>> (8 - len));

            return temp & 0xff;
        } else {
            int firstTemp = ((((bs[firstArrayIndex] & 0xff) << firstBit) & 0xff) >>> firstBit);
            int lastTemp = (((bs[lastArrayIndex] & 0xff) >>> (7 - lastBit)));
            int length = lastArrayIndex - firstArrayIndex + 1;
            // 第一组赋值
            result |= (firstTemp & 0xff) << ((length - 1) * 8) - (7 - lastBit);
            // 中间几组的赋值
            for (int i = 1; i < length - 1; i++) {
                result |= ((bs[firstArrayIndex + i] & 0xff) << ((length - i - 1) * 8) - (7 - lastBit));
            }
            // 最后一组的赋值
            result |= ((lastTemp & 0xff));

            return result;
        }
    }


    /**
     * @param nodes
     * @return
     */
    public static byte[] parseLocation(List<Node> nodes) {
        if (!nodes.isEmpty()) {
            byte[] bs = new byte[nodes.size() * 4];
            for (int i = 0; i < nodes.size(); i++) {
                Node node = nodes.get(i);
                addToByte(bs, i * 4, parseLocation(node));
            }
            return bs;
        } else {
            throw new RuntimeException("节点集合为空！无法解析！");
        }
    }

    public static byte[] addToBytehalf(byte[] longBs, int index, int value1,int value2, int byteNum) {
        byte[] bs = parseToBytehalf(value1,value2, byteNum);
        for (int i = 0; i < bs.length; i++) {
            longBs[index + i] = bs[i];
        }
        return longBs;
    }
    public static byte[] parseLocation(Node coord) {
        byte[] bs = new byte[4];
        bs[0] = (byte) coord.getX();
        bs[1] = (byte) coord.getY();
        bs[2] = (byte) coord.getZ();
        int resAction = 0;
        if (coord.getResAction() != null) {
            resAction = coord.getResAction() == Action.CHANGE_TO_ROADWAY ?
                    Order.CHANGE_TO_ROADWAY.getOrderByte() : Order.CHANGE_TO_RAMP.getOrderByte();
        }
        bs[3] = (byte) (resAction);
        return bs;
    }

    /**
     * xyz在低三位
     *
     * @param x
     * @param y
     * @param z
     * @return
     */
    public static int parseLocation(int x, int y, int z) {
        byte[] bs = new byte[4];
        bs[1] = (byte) x;
        bs[2] = (byte) y;
        bs[3] = (byte) z;
        int num = bs[3] & 0xFF;
        num |= ((bs[2] << 8) & 0xFF00);
        num |= ((bs[1] << 16) & 0xFF0000);
        num |= ((bs[0] << 24) & 0xFF0000);
        return num;
    }

    public static Node parseToCoord(int no) {
        int z = (byte) no;
        int y = (byte) (no >> 8) & 0xFF;
        int x = (byte) (no >> 16) & 0xFF;
        return new Node(x, y, z);
    }

    private static byte[] parseToBytehalf(int value1, int value2,int byteNum) {
        byte[] bs = new byte[byteNum];
        bs[byteNum - 1] = (byte) (((value1<< 4)& 0xF0)|(value2&0x0f));
        return bs;
    }
    public static Node parseToCoord1(int no) {
        int y = (byte) no;
        int x = (byte) (no >> 8) & 0xFF;

        return new Node(x, y, 0);
    }

    private static byte[] parseToByte(int value, int byteNum) {
        byte[] bs = new byte[byteNum];
        for (int i = 0; i < byteNum; i++) {
            bs[byteNum - 1 - i] = (byte) ((value >> i * 8) & 0xFF);
        }
        return bs;
    }

    /**
     * 将value以字节形式添加到longBs中
     *
     * @param longBs
     * @param index   添加的位置
     * @param value   被添加的数
     * @param byteNum value所占字节数
     * @return
     */
    public static byte[] addToByte(byte[] longBs, int index, int value, int byteNum) {
        byte[] bs = parseToByte(value, byteNum);
        for (int i = 0; i < bs.length; i++) {
            longBs[index + i] = bs[i];
        }
        return longBs;
    }

    public static byte[] addToByte(byte[] longBs, int index, byte[] shortBs) {
        for (int i = 0; i < shortBs.length; i++) {
            longBs[index + i] = shortBs[i];
        }
        return longBs;
    }


}
